/*
 某计算机系统只有以下原子操作：
		 赋值
		 +1运算
		 循环[只能是固定次数的循环]
		 只操作0和正整数
		 不会溢出
 用伪代码实现加法，减法，乘法和除法运算。 
 */

#include "junix.h"

#define loop(n) for(uint64_t i=0;i<(n);i++)

uint64_t add(uint64_t a, uint64_t b) {
	uint64_t result = a;
	loop(b) {
		++result;
	}

	return result;
}	

uint64_t dec(uint64_t a) // 减一
{
	uint64_t result=0,tmp = 0;
	loop(a) {
		result = tmp;
		++tmp;
	}

	return result;
}

uint64_t minus(uint64_t a, uint64_t b) {
	uint64_t result = a;
	loop(b) {
		result=dec(result);
	}

	return result;
}

uint64_t multiply(uint64_t a, uint64_t b) {
	uint64_t result = 0;
	loop(b){
		result=add(result,a);
	}

	return result;
}



//Nx = 0 if x>0
//Nx = 1 if x==0
uint64_t Nx(uint64_t x) {
	uint64_t accu = 1, beg = 0;
	loop(x){
		++beg;
		accu = multiply(accu,dec(beg));
	}

	return accu;
}

// NNx = 0 iff x==0
// NNx = 1 iff x != 0
uint64_t NNx(uint64_t x) {
	return minus(1,Nx(x));
}

//宋方敏<<计算导论>>
uint64_t divide(uint64_t a, uint64_t b) {
	uint64_t result=0;
	uint64_t beg=0;
	uint64_t tmp=0;

	loop(a) {
		++beg;
		tmp = multiply(b,beg);
		tmp = minus(tmp,a);
		tmp = Nx(tmp);
		result = add(result,tmp);
	}

	return result*NNx(b);
}


int main(int argc, char **argv)
{
	assert(::add(9,8)==17);

	assert(::minus(9,5)==4);
	assert(::minus(9,10)==0);

	assert(::multiply(9,8)==72);

	assert(::Nx(0)==1);
	assert(::Nx(1)==0);
	assert(::Nx(10000)==0);

	assert(divide(8,3)==2);
	assert(divide(1000,2)==500);
}
